#include "AutoFind.h"

std::string convertAnsiToUtf8(const std::string& ansiString) {
    int requiredSize = ::MultiByteToWideChar(CP_ACP, 0, ansiString.c_str(), -1, nullptr, 0);
    std::wstring wideString(requiredSize, 0);
    ::MultiByteToWideChar(CP_ACP, 0, ansiString.c_str(), -1, &wideString[0], requiredSize);

    requiredSize = ::WideCharToMultiByte(CP_UTF8, 0, wideString.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string utf8String(requiredSize, 0);
    ::WideCharToMultiByte(CP_UTF8, 0, wideString.c_str(), -1, &utf8String[0], requiredSize, nullptr, nullptr);

    return utf8String;
}

// 跨平台函数：执行命令并超时终止
static inline bool executeCommandWithTimeout(const std::string& command, int timeoutSeconds,std::string& output) {

#if defined(_WIN32) || defined(_WIN64)
        // Windows 实现
        /* 创建匿名管道 */
        SECURITY_ATTRIBUTES sa;
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
        HANDLE hReadPipe, hWritePipe;
        if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
            throw std::runtime_error("创建进程失败: " + std::to_string(GetLastError()));
            return false;
        }
        // 设置子进程的标准输出重定向到管道
        PROCESS_INFORMATION pi= { 0 };
        STARTUPINFO si = { 0 };
        si.cb = sizeof(STARTUPINFO);
        GetStartupInfo(&si);
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	    si.wShowWindow = SW_HIDE; // 隐藏cmd执行的窗口
        si.hStdOutput = hWritePipe;
        si.hStdError = hWritePipe;

        if (!CreateProcessA(NULL, const_cast<LPSTR>(command.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
            CloseHandle(hReadPipe);
            CloseHandle(hWritePipe);
            throw std::runtime_error("创建进程失败: " + std::to_string(GetLastError()));
            return false;
        }

        // 等待进程完成或超时
        DWORD waitResult = WaitForSingleObject(pi.hProcess, timeoutSeconds * 1000);
        if (waitResult == WAIT_TIMEOUT) {
            // 超时，终止进程
            log_info("进程执行超时,正在强制终止...");
            TerminateProcess(pi.hProcess, 300);
        }
//        else {
//            std::cout << "进程执行完成." << std::endl;
//        }

         CloseHandle(hWritePipe);
        // 读取管道中的输出
        DWORD bytesRead;
        char buffer[4096];
        while (true) {
            if (!ReadFile(hReadPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) || bytesRead == 0) {
                break;
            }
            buffer[bytesRead] = '\0';
            output += std::string(buffer, bytesRead);
            //log_info(output.c_str());
        }
        CloseHandle(hReadPipe);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return (waitResult != WAIT_TIMEOUT);
#elif defined(__linux__)
    // Linux 实现
        pid_t pid = fork();

        if (pid == 0) {
            // 子进程执行命令
            int pipefd[2];
            if (pipe(pipefd) == -1) {
                std::cerr << "创建管道失败." << std::endl;
                exit(1);
            }

            dup2(pipefd[1], STDOUT_FILENO);
            dup2(pipefd[1], STDERR_FILENO);
            close(pipefd[0]);
            close(pipefd[1]);

            execl("/bin/sh", "sh", "-c", command.c_str(), NULL);
            exit(127); // 如果 execl 失败
        } else if (pid < 0) {
            std::cerr << "创建进程失败." << std::endl;
            return false;
        }

        // 父进程等待子进程完成或超时
        bool processActive = true;
        bool timedOut = false;
        int pipefd[2];
        if (pipe(pipefd) == -1) {
            std::cerr << "创建管道失败." << std::endl;
            return false;
        }

        pid_t childPid = pid;
        std::thread checker([&] {
            std::this_thread::sleep_for(std::chrono::seconds(timeoutSeconds));
            if (processActive) {
                std::cerr << "进程执行超时，正在杀死进程..." << std::endl;
                kill(childPid, SIGKILL);
                timedOut = true;
            }
        });

        // 读取子进程的输出
        char buffer[4096];
        ssize_t bytes_read;
        while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer))) > 0) {
            output.append(buffer, bytes_read);
        }

        close(pipefd[0]);
        close(pipefd[1]);

        int status;
        waitpid(childPid, &status, 0);
        processActive = false;
        checker.join();

        if (timedOut) {
            return false;
        } else {
            std::cout << "进程执行完成." << std::endl;
            return true;
        }
#else
#error "Unsupported operating system"
#endif
    return true;
}

///键盘测试
#if defined(_WIN32) || defined(_WIN64)
HHOOK hKeyboardHook = NULL;
// 键盘钩子回调函数
LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode >= 0 && wParam == WM_KEYDOWN) {
        KBDLLHOOKSTRUCT* pKeyboard = (KBDLLHOOKSTRUCT*)lParam;

    }
    MessageBoxA(NULL,(LPCSTR)"这是一个错误消息框示例",(LPCSTR)"错误",MB_ICONERROR);
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

 void testKeyboard(bool start){
    if(start){
        hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandle(NULL),0);
        if (hKeyboardHook == NULL) {
            throw std::runtime_error("安装键盘钩子失败" );
            log_info("2222");
        }
        log_info("3333");
    }else{
        // 卸载键盘钩子
        if(hKeyboardHook != NULL){
            UnhookWindowsHookEx(hKeyboardHook);
            hKeyboardHook = NULL;
        }
        log_info("4444");
    }
}

#elif defined(__linux__)

static void testKeyboard(bool start){

}

#else
#error "Unsupported operating system"
#endif

TestStatus testStatus;
extern void TestSimple(cJSON *root);
extern void TestSimpleV1(cJSON *root);
extern void TestSimpleV2(cJSON *root);

void CMDHandle::handleTest(cJSON *test)
{
    std::string key = std::string(cJSON_GetStringValue(cJSON_GetObjectItem(test, "key")));
    bool start = cJSON_IsTrue(cJSON_GetObjectItem(test, "start"));
    if(!start){
        ///关闭一些耗时测试以及无法自动关闭的测试
        testStatus[key] = false;
        return;
    }
    std::string name = cJSONArray_toString(cJSON_GetObjectItem(test, "name"));
    std::string cmd = cJSONArray_toString(cJSON_GetObjectItem(test, "data"));
    int timeout = cJSON_GetObjectItem(test,"timeout")->valueint;

    ///显示乱码，终端执行chcp 65001
    log_info("get cmd test Item -> %s(%s:%d):%s", name.c_str(),key.c_str(),timeout,cmd.c_str());
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root,"cmd",SocketCMD::test);
    cJSON_AddStringToObject(root,"key",key.c_str());
    cJSON_AddStringToObject(root,"output","");
    try {
        if(key.compare("cmd") == 0) {
            std::string output = "";
            cJSON_ReplaceItemInObject(root,"cmd",cJSON_CreateNumber(SocketCMD::cmd));
            executeCommandWithTimeout(cmd,timeout,output);
            log_info("输出结果:\n%s",convertAnsiToUtf8(output).c_str());
            cJSON_ReplaceItemInObject(root,"output",cJSON_CreateString(convertAnsiToUtf8(output).c_str()));
        }else if(key.compare("keyboard") == 0) {
            testKeyboard(true);
        }else if(key.compare("simple") == 0){
            ThreadPool::getInstance()->submitTask(TestSimple,root);
            return;
        }else if(key.compare("simple-v1") == 0){
            ThreadPool::getInstance()->submitTask(TestSimpleV1,root);
            return;
        }else if(key.compare("simple-v2") == 0){
            ThreadPool::getInstance()->submitTask(TestSimpleV2,root);
            return;
        }else{
            throw std::runtime_error("can\'t handle test item");
        }
    } catch (const std::exception& e) {
        log_error("run %s err:%s",name.c_str(),e.what());
        cJSON_AddStringToObject(root,"output",("can\'t handle test item -> "+name).c_str());
    }
    SEND_PACK(root);
    cJSON_Delete(root);
}